#include "PWMDriver2.h"
#include "DSP2833x_Device.h"
#include "DSP2833x_EPwm_defines.h"

// SYSCLKOUT (System Clock) = 150Mhz
// TBCLK = 150Mhz (divide by (1*1))
// PWMClock = 20kHz (TBCLK/(7499+1)) [50us]

bool PWMDriver2::Init() 
{
	EALLOW;
	// configure GPIO pins
	GpioCtrlRegs.GPAPUD.bit.GPIO4 = 0;    // Enable pull-up on GPIO4 (EPWM3A)
    GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0;    // Enable pull-up on GPIO5 (EPWM3B)   
    GpioCtrlRegs.GPAPUD.bit.GPIO6 = 0;    // Enable pull-up on GPIO6 (EPWM4A)
    GpioCtrlRegs.GPAPUD.bit.GPIO7 = 0;    // Enable pull-up on GPIO7 (EPWM4B)  
    GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;   // Configure GPIO4 as EPWM3A
    GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1;   // Configure GPIO5 as EPWM3B
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1;   // Configure GPIO6 as EPWM4A
    GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 1;   // Configure GPIO7 as EPWM4B
    EDIS;
    
    // Setup TBCLK
	EPwm3Regs.TBPRD = 7499; // Period = 7500 TBCLK counts
	EPwm3Regs.CMPA.half.CMPA = 0; // Compare A = 0% duty 
	EPwm3Regs.CMPB = 0; // Compare B = 0% duty
	EPwm3Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero
	EPwm3Regs.TBCTR = 0; // clear TB counter
	EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
	EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Phase loading disabled
	EPwm3Regs.TBCTL.bit.PRDLD = TB_SHADOW;
	EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
	EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // TBCLK = SYSCLK
	EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1; // divide by 64
	EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
	EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
	EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR = Zero
	EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR = Zero
	EPwm3Regs.AQCTLA.bit.ZRO = AQ_SET;
	EPwm3Regs.AQCTLA.bit.CAU = AQ_CLEAR;
	EPwm3Regs.AQCTLB.bit.ZRO = AQ_SET;
	EPwm3Regs.AQCTLB.bit.CBU = AQ_CLEAR;
	
	// Setup TBCLK
	EPwm4Regs.TBPRD = 7499; // Period = 7500 TBCLK counts
	EPwm4Regs.CMPA.half.CMPA = 0; // Compare A = 5% duty 
	EPwm4Regs.CMPB = 0; // Compare B = 5% duty
	EPwm4Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero
	EPwm4Regs.TBCTR = 0; // clear TB counter
	EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
	EPwm4Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Phase loading disabled
	EPwm4Regs.TBCTL.bit.PRDLD = TB_SHADOW;
	EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
	EPwm4Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // TBCLK = SYSCLK
	EPwm4Regs.TBCTL.bit.CLKDIV = TB_DIV1; // divide by 64
	EPwm4Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
	EPwm4Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
	EPwm4Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR = Zero
	EPwm4Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR = Zero
	EPwm4Regs.AQCTLA.bit.ZRO = AQ_SET;
	EPwm4Regs.AQCTLA.bit.CAU = AQ_CLEAR;
	EPwm4Regs.AQCTLB.bit.ZRO = AQ_SET;
	EPwm4Regs.AQCTLB.bit.CBU = AQ_CLEAR;
	
	// reset all to zero!
	SetPWM(0, 0);
	SetPWM(1, 0);
	SetPWM(2, 0);
	SetPWM(3, 0);
	
    return true;
}

// dutyCycle: (0.0...100.0) [%]
void PWMDriver2::SetPWM(int index, float dutyCycle)
{
	Uint16 duty = (Uint16)((dutyCycle/100.0f)*7500.0f);
	if( index == 0 )
	{
		// PWM3A
		EPwm3Regs.CMPA.half.CMPA = duty; // adjust duty for output EPWM1A
		
	}
	else if( index == 1 )
	{
		// PWM3B
		EPwm3Regs.CMPB = duty; // adjust duty for output EPWM1B
	}
	else if( index == 2 )
	{
		// PWM4A
		EPwm4Regs.CMPA.half.CMPA = duty; // adjust duty for output EPWM2A
	}
	else if( index == 3 )
	{
		// PWM4B
		EPwm4Regs.CMPB = duty; // adjust duty for output EPWM2B
	}
}
